본문으로 건너뛰기

23.07.27

오늘 한 일

  • 카공실록 폴더 구조 변경 PR
  • gloddy PR 반영 및 리뷰

🤔생각

타입들을 어디에다 관리해야할까?

카공실록 폴더 구조를 변경하면서 타입들을 어디에다 관리해야할지 고민했다.

지금 타입이 관리되고 있는 곳은 다음과 같다.

  • src/types
  • src/app/페이지명/types
  • src/apis/도메인명/types

src에 있는 타입 파일은 공통적으로 사용되는 타입들을 관리하고,
app에 있는 타입 파일은 해당 페이지에서만 사용되는 타입들을 관리하고,
apis에 있는 타입 파일은 해당 도메인에서만 사용되는 타입들을 관리한다.

근데, 공통적인 것들은 전역에서 사용하는 타입이니 namespace로 declare해서 관리하는 것도 괜찮겠다고 생각이 들었다.

위와 같은 생각을 한 이유

프로젝트에서는 특이하게 타입들을 관리하고 있었다.

api 호출해서 가져오는 DTO들은 어디서든 사용될 가능성이 있고, 가져와서 Omit, Pick 등 처리해서 커스텀 타입을 얼마든지 만들 수 있기 때문에 namespace로 관리해서 전역에서 사용할 수 있도록 했다.

이렇게 하면 import하지 않아도 되어 깔끔해지고 타입들을 관리하기도 편해진다.

성능에 문제가 있을까? ❌

문제없다. 어차피 컴파일 과정에서 type들은 제외되기 때문에 (namespace에 type만 작성한다면) 없는 것과 같다.

적용해보자

나는 저 프로젝트처럼 DTO 타입을 다 전역으로 관리하진 않았고, 공통적으로 사용하는 타입만 전역으로 관리하기로 했다.

그래서 src/@typesindex.d.ts를 만들고, 거기에 공통적으로 사용하는 타입들을 관리하기로 했다.

declare namespace Common {
interface Response<T> {
result?: string;
message?: string;
data: T;
}
type Modify<T, R> = Omit<T, keyof R> & R;
}

이렇게 하면 Common.ResponseCommon.Modify처럼 어디서든 사용할 수 있다.

사용 용례

export const postImages = async (payload: ImagesPayload) => {
const { data } = await api
.post('api/v1/images', {
json: payload,
})
.json<Common.Response<{ images: Image[] }>>();

return data;
};
export interface Place {
id: number;
name: string;
address: string;
latitude: number;
longitude: number;
imageIds: number[];
tags: string[]; // ['#조용한', '#나만알고싶은', '#노트북']
rating: number;
isOpen: boolean;
phone: string; // 02-1234-1234
links: {
linkType: LinkType;
url: string;
}[];
businessHours: [
Common.Modify<BusinessHour, { dayOfWeek: 'MONDAY' }>,
Common.Modify<BusinessHour, { dayOfWeek: 'TUESDAY' }>,
Common.Modify<BusinessHour, { dayOfWeek: 'WEDNESDAY' }>,
Common.Modify<BusinessHour, { dayOfWeek: 'THURSDAY' }>,
Common.Modify<BusinessHour, { dayOfWeek: 'FRIDAY' }>,
Common.Modify<BusinessHour, { dayOfWeek: 'SATURDAY' }>,
Common.Modify<BusinessHour, { dayOfWeek: 'SUNDAY' }>
];
}

Modify는 기존의 타입을 쉽게 수정할 수 있도록 도와주는 타입이다. 원래라면 조금 지저분하게 처리해야했다.

businessHours: [
Omit<BusinessHour, 'dayOfWeek'> & { dayOfWeek: 'MONDAY' },
Omit<BusinessHour, 'dayOfWeek'> & { dayOfWeek: 'TUESDAY' },
Omit<BusinessHour, 'dayOfWeek'> & { dayOfWeek: 'WEDNESDAY' },
Omit<BusinessHour, 'dayOfWeek'> & { dayOfWeek: 'THURSDAY' },
Omit<BusinessHour, 'dayOfWeek'> & { dayOfWeek: 'FRIDAY' },
Omit<BusinessHour, 'dayOfWeek'> & { dayOfWeek: 'SATURDAY' },
Omit<BusinessHour, 'dayOfWeek'> & { dayOfWeek: 'SUNDAY' },
];

dayOfWeek를 두 번 써야해서 커스텀 타입 만들어서 작성했다.

루트 페이지에서 쓰이는 컴포넌트는 어떻게 관리하지??

src/app에 컴포넌트 폴더를 만들어버리면 페이지로 보일 것 같았다. 그래서 다음과 같이 처리했다.

┣ (home)
┃ ┣ components
┃ ┃ ┣ Nav
┃ ┃ ┃ ┗ index.tsx
┃ ┃ ┣ PlaceItem
┃ ┃ ┃ ┗ index.tsx
┃ ┃ ┗ index.ts
┃ ┗ page.tsx

이렇게 group화 시켜서 관리해도 동일하게 동작한다.


내일 할 일

  • 타입스크립트 스터디 진행
  • gloddy 개발